package com.ruoyi.docs.service.impl;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;
import java.util.List;

import com.ruoyi.docs.domain.BizPeopleActivity;
import org.apache.commons.io.output.ByteArrayOutputStream;
import cn.hutool.core.img.FontUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.ruoyi.common.annotation.CommunityScope;
import com.ruoyi.common.config.WxServiceProperties;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.BizTree;
import com.ruoyi.common.core.domain.entity.BizCommunity;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.docs.domain.BizArticle;
import com.ruoyi.docs.domain.BizColumn;
import com.ruoyi.docs.domain.dto.ArticleTreeDto;
import com.ruoyi.organization.domain.BizPeople;
import com.ruoyi.organization.domain.vo.SchemaQrCodeVo;
import com.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import com.ruoyi.docs.mapper.BizActivityMapper;
import com.ruoyi.docs.domain.BizActivity;
import com.ruoyi.docs.service.IBizActivityService;
import org.w3c.dom.Element;

import javax.annotation.Resource;
import javax.imageio.*;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.w3c.dom.Element;

import javax.annotation.Resource;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageOutputStream;
import javax.servlet.http.HttpServletResponse;
/**
 * 活动列表Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-06-04
 */
@Service
public class BizActivityServiceImpl implements IBizActivityService 
{
    @Autowired
    private BizActivityMapper bizActivityMapper;

    @Autowired
    private BizColumnServiceImpl bizColumnService;
    @Resource
    private ISysConfigService sysConfigService;

    @Resource
    private WxServiceProperties wxServiceProperties;
    @Autowired
    private BizPeopleActivityServiceImpl bizPeopleActivityServ;
    /**
     * 查询活动列表
     * 
     * @param activityId 活动列表主键
     * @return 活动列表
     */
    @Override
    public BizActivity selectBizActivityByActivityId(Long activityId)
    {
        return bizActivityMapper.selectBizActivityByActivityId(activityId);
    }

    /**
     * 查询活动列表列表
     * 
     * @param bizActivity 活动列表
     * @return 活动列表
     */
    @Override
    @CommunityScope
    public List<BizActivity> selectBizActivityList(BizActivity bizActivity)
    {
        return bizActivityMapper.selectBizActivityList(bizActivity);
    }

    /**
     * 新增活动列表
     * 
     * @param bizActivity 活动列表
     * @return 结果
     */
    @Override
    public int insertBizActivity(BizActivity bizActivity)
    {
        if (bizActivity.getType().equals(0)) {
            bizActivity.setBookingStart(bizActivity.getExpireStart());
            bizActivity.setBookingEnd(bizActivity.getExpireEnd());
        }
        bizActivity.setCreateTime(DateUtils.getNowDate());
        return bizActivityMapper.insertBizActivity(bizActivity);
    }

    /**
     * 修改活动列表
     * 
     * @param bizActivity 活动列表
     * @return 结果
     */
    @Override
    public int updateBizActivity(BizActivity bizActivity)
    {
        BizPeopleActivity bizPeopleActivity = new BizPeopleActivity();
        if (bizActivity.getExpireEnd() != null &&  bizActivity.getType().equals(0)) {
            bizActivity.setBookingStart(bizActivity.getExpireStart());
            bizActivity.setBookingEnd(bizActivity.getExpireEnd());
        }
        bizActivity.setUpdateTime(DateUtils.getNowDate());

        bizPeopleActivity.setActivityId(bizActivity.getActivityId());
        bizPeopleActivity.setTitle(bizActivity.getTitle());
        bizPeopleActivity.setExpireStart(bizActivity.getExpireStart());
        bizPeopleActivity.setExpireEnd(bizActivity.getExpireEnd());
        if (Objects.nonNull(bizPeopleActivity.getTitle())) {
            bizPeopleActivityServ.updateRelationBizPeopleActivity(bizPeopleActivity);
        }
        return bizActivityMapper.updateBizActivity(bizActivity);
    }

    /**
     * 批量删除活动列表
     *
     * @param activityIds 需要删除的活动列表主键集合
     * @return 结果
     */
    @Override
    public int deleteBizActivityByActivityIds(Long[] activityIds) {
        return this.bizActivityMapper.deleteBizActivityByActivityIds(activityIds);
    }

    /**
     * 生成成名身份牌
     *
     * @param response
     * @param activityId
     */
    private void generateCard(HttpServletResponse response, Long activityId) {
        BizActivity activity = this.selectBizActivityByActivityId(activityId);
        if (ObjectUtil.isNull(activity)) {
            throw new ServiceException("活动不存");
        }
        // 图片尺寸
        int width = 595;
        int height = 842;
        // 创建空白图片
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 获取绘图对象
        Graphics2D graphics2D = ImgUtil.createGraphics(bufferedImage, null);// 设置抗锯齿
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        BufferedImage bgImage = ImgUtil.read(ResourceUtil.getResource("material/smqd.png"));
        // 检查背景图片是否小于目标图片尺寸，如果是，则按比例缩放背景图片
        if (bgImage.getWidth() != width || bgImage.getHeight() != height) {
            double scale = Math.min((double) width / bgImage.getWidth(), (double) height / bgImage.getHeight());
            bgImage = bufferedImageResize(bgImage, (int) (bgImage.getWidth() * scale), (int) (bgImage.getHeight() * scale));
        }
        // 将背景图片绘制到目标图片上
        graphics2D.drawImage(bgImage, 0, 0, width, height, null);

        // 如果需要，这里可以添加更多图形操作，如绘制二维码等
        Font font = FontUtil.createFont(ResourceUtil.getStreamSafe("font/YouSheBiaoTiHei-2.ttf"));
        // 文本颜色
        Color textColor = Color.BLACK;
        // 文本可用的宽度
        int textWidth = bufferedImage.getWidth();

        // 1. 名字
        addTextToImage(bufferedImage, "“"+activity.getTitle()+"”", font.deriveFont(Font.PLAIN, 40), textColor, textWidth, 720);

        try {
            SchemaQrCodeVo schemaQrCodeVo = new SchemaQrCodeVo();
            schemaQrCodeVo.setPagePath(Constants.WX_MP_PAGE_SCAN_AT_PATH);
            schemaQrCodeVo.setScene("a=3&q=" + activityId);
            schemaQrCodeVo.setEnvVersion(sysConfigService.selectConfigByKey(Constants.WX_MP_ENV_VERSION));
            String post = HttpUtil.post(wxServiceProperties.getHostPath() + wxServiceProperties.getApiSuffix().getSchemaQrCode(), JSONUtil.toJsonStr(schemaQrCodeVo), 60000);
            byte[] data = JSONUtil.parseObj(post).get("data", byte[].class);
            if (ObjectUtil.isNull(data)) {
                throw new ServiceException("获取微信二维码失败");
            }
            graphics2D.drawImage(generateQRCode(data, 320), (bufferedImage.getWidth() - 300) / 2, 290, null);
        } catch (Exception e) {
            throw new ServiceException("获取微信二维码失败");
        }
        // 关闭绘图上下文
        graphics2D.dispose();
        try {
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, IdUtil.fastSimpleUUID() + "." + ImgUtil.IMAGE_TYPE_JPEG);
            byte[] process = process(bufferedImage, 300);
            response.getOutputStream().write(process);
        } catch (IOException e) {
            throw new RuntimeException("下载身份牌失败");
        }
    }

    private static BufferedImage bufferedImageResize(BufferedImage bgImage, int width, int height) {
        //图片缩放
        BufferedImage updateImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 获取 Graphics2D 对象
        Graphics2D g2d = updateImage.createGraphics();
        // 设置抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // 清除背景，使其完全透明
        g2d.setComposite(AlphaComposite.Clear);
        g2d.fillRect(0, 0, width, height);
        g2d.setComposite(AlphaComposite.SrcOver);
        //放大图片
        g2d.drawImage(bgImage, 0, 0, width, height, null);
        return updateImage;
    }
    /**
     * 删除活动列表信息
     * 
     * @param activityId 活动列表主键
     * @return 结果
     */
    @Override
    public int deleteBizActivityByActivityId(Long activityId)
    {
        return bizActivityMapper.deleteBizActivityByActivityId(activityId);
    }

    /**
     * 活动的树形
     *
     * @return
     */
    @Override
    public List<BizTree> getTree(ArticleTreeDto articleTreeDto) {
        BizColumn column = new BizColumn();
        column.setColumnType(1L);
        List<BizColumn> bizColumns = bizColumnService.selectBizColumnList(column);
        List<BizTree> trees = new ArrayList();
        for (BizColumn bizColumn : bizColumns) {
            if (bizColumn.getParentId().equals(0L)) {
                BizTree bizTree = new BizTree();
                bizTree.setValue(bizColumn.getColumnId().toString());
                bizTree.setLabel(bizColumn.getColumnName());
                trees.add(bizTree);
            }
        }
        for (BizTree tree : trees) {
            List<BizTree.FirstChildren> childrens = new ArrayList<>();
            for (BizColumn bizColumn : bizColumns) {
                if (tree.getValue().equals(bizColumn.getParentId().toString())) {
                    BizTree.FirstChildren children = new BizTree.FirstChildren();
                    children.setValue(bizColumn.getColumnId().toString());
                    children.setLabel(bizColumn.getColumnName());
                    childrens.add(children);
                }
            }
            tree.setChildren(childrens);
        }
        //当前分类下的文章
        for (BizTree tree : trees) {
            if (StringUtils.isNotEmpty(tree.getChildren())){
                for (BizTree.FirstChildren child : tree.getChildren()) {
                    BizActivity bizActivity = new BizActivity();
                    bizActivity.setColumnId(Long.parseLong(child.getValue()));
                    bizActivity.setStatus("0");
                    if (articleTreeDto != null && articleTreeDto.getCommunityId() != null) {
                        bizActivity.setCommunityId(articleTreeDto.getCommunityId());
                    }
                    List<BizActivity> activities = this.selectBizActivityList(bizActivity);
                    List<BizTree.FirstChildren> articleTree = new ArrayList<>();
                    for (BizActivity activity : activities) {
                        BizTree.FirstChildren bizTree = new BizTree.FirstChildren();
                        bizTree.setValue(activity.getActivityId().toString());
                        bizTree.setLabel(activity.getTitle());
                        articleTree.add(bizTree);
                    }
                    child.setChildren(articleTree);
                }
            }
            else {
                BizActivity bizActivity = new BizActivity();
                bizActivity.setColumnId(Long.parseLong(tree.getValue()));
                bizActivity.setStatus("0");
                if (articleTreeDto != null && articleTreeDto.getCommunityId() != null) {
                    bizActivity.setCommunityId(articleTreeDto.getCommunityId());
                }
                List<BizActivity> activities = this.selectBizActivityList(bizActivity);
                List<BizTree.FirstChildren> articleTree = new ArrayList<>();
                for (BizActivity activity : activities) {
                    BizTree.FirstChildren bizTree = new BizTree.FirstChildren();
                    bizTree.setValue(activity.getActivityId().toString());
                    bizTree.setLabel(activity.getTitle());
                    articleTree.add(bizTree);
                }
                tree.setChildren(articleTree);
            }
        }
        return trees;
    }

    /**
     * 创建二维码
     *
     * @param response
     * @param activityId
     */
    @Override
    public void createQrcode(HttpServletResponse response, Long activityId) {
        this.generateCard(response, activityId);
    }

    // 在图片上添加文本，支持手动换行，文本水平居中
    private static void addTextToImage(BufferedImage baseImage, String text, Font font, Color color, int maxWidth, int y) {
        Graphics2D g2d = baseImage.createGraphics();
        // 设置抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2d.setFont(font);
        g2d.setColor(color);

        FontMetrics fm = g2d.getFontMetrics();
        int lineHeight = fm.getHeight();
        int currentY = y;
        String[] lines = text.split("\n");

        for (String line : lines) {
            int lineWidth = fm.stringWidth(line);
            // 居中
            int lineX = (maxWidth - lineWidth) / 2;
            g2d.drawString(line, lineX, currentY);
            currentY += lineHeight;
        }
        g2d.dispose();
    }

    // 生成二维码图片
    private static BufferedImage generateQRCode(String text, int size) {
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        try {
            QRCodeWriter writer = new QRCodeWriter();
            BitMatrix bitMatrix = writer.encode(text, BarcodeFormat.QR_CODE, size, size, hints);
            int width = bitMatrix.getWidth();
            int height = bitMatrix.getHeight();
            BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D graphics = qrImage.createGraphics();
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            graphics.setColor(Color.WHITE);
            graphics.fillRect(0, 0, size, size);
            graphics.setColor(Color.BLACK);

            for (int x = 0; x < size; x++) {
                for (int y = 0; y < size; y++) {
                    if (bitMatrix.get(x, y)) {
                        graphics.fillRect(x, y, 1, 1);
                    }
                }
            }

            // 渲染二维码
            Graphics2D graphics1 = qrImage.createGraphics();
            graphics1.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            // 添加蓝色边框
            int borderSize = 10; // 边框大小
            Color myColor = new Color(0x19, 0x76, 0xFF); // 红色
            graphics1.setColor(myColor);
            graphics1.fillRect(0, 0, size, borderSize); // 上边框
            graphics1.fillRect(0, 0, borderSize, size); // 左边框
            graphics1.fillRect(size - borderSize, 0, borderSize, size); // 右边框
            graphics1.fillRect(0, size - borderSize, size, borderSize); // 下边框
            return qrImage;
        } catch (WriterException e) {
            e.printStackTrace();
            return null;
        }
    }

    // 生成二维码图片
    private static BufferedImage generateQRCode(byte[] bytes, int size) {
        BufferedImage qrImage = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics = qrImage.createGraphics();
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, 0, size, size);
        graphics.setColor(Color.BLACK);
        graphics.drawImage(ImgUtil.read(new ByteArrayInputStream(bytes)), 0, 0, size, size, null);


        // 渲染二维码
        Graphics2D graphics1 = qrImage.createGraphics();
        graphics1.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // 添加蓝色边框
        int borderSize = 10; // 边框大小
        Color myColor = new Color(255, 255, 255, 0); // 红色
        graphics1.setColor(myColor);
        graphics1.fillRect(0, 0, size, borderSize); // 上边框
        graphics1.fillRect(0, 0, borderSize, size); // 左边框
        graphics1.fillRect(size - borderSize, 0, borderSize, size); // 右边框
        graphics1.fillRect(0, size - borderSize, size, borderSize); // 下边框
        return qrImage;
    }
    public static byte[] process(BufferedImage image, int dpi) throws IOException {
        for (Iterator<ImageWriter> iw = ImageIO.getImageWritersByFormatName("jpeg"); iw.hasNext(); ) {
            ImageWriter writer = iw.next();
            ImageWriteParam writeParams = writer.getDefaultWriteParam();
            writeParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            //调整图片质量
            writeParams.setCompressionQuality(1f);
            IIOMetadata data = writer.getDefaultImageMetadata(new ImageTypeSpecifier(image), writeParams);
            Element tree = (Element) data.getAsTree("javax_imageio_jpeg_image_1.0");
            Element jfif = (Element) tree.getElementsByTagName("app0JFIF").item(0);
            jfif.setAttribute("Xdensity", dpi + "");
            jfif.setAttribute("Ydensity", dpi + "");
            jfif.setAttribute("resUnits", "1");
            data.mergeTree("javax_imageio_jpeg_image_1.0", tree);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ImageOutputStream stream = null;
            try {
                stream = ImageIO.createImageOutputStream(out);
                writer.setOutput(stream);
                writer.write(null, new IIOImage(image, null, data), writeParams);
            } finally {
                stream.close();
            }
            return out.toByteArray();
        }
        return null;
    }

}
